#include "TCanvas.h"
#include "TROOT.h"
#include "TGraphErrors.h"
#include "TF1.h"
#include "TH2.h"
#include "TH1.h"
#include "TFile.h"
#include "TLegend.h"
#include "TArrow.h"
#include "TLatex.h"
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <math.h>
#include <dirent.h>
using namespace std;
float strToFloat(string base , int dp = 0);
string nameGen(string ,int ,string);
string findTB(string ,string);
string findMHp(string ,string);
vector<string> getFlags(string);
bool findSUSY(string);
bool isThere(string ,string ,string);
string rightFlag(string);
int findNumberOfFiles(string);
void twoDRootGenerator(){ 
    int N = findNumberOfFiles("FH/");
    vector<string> SH_flags = {"ggh XS in pb" ,"bbh XS in pb" ,"ggh XS in pb" ,"bbh XS in pb" ,"ggh XS in pb" ,"bbh XS in pb"};
    vector<string> SH_labels = {"ggh XS for H1" ,"bbh XS for H1" ,"ggh XS for H2" ,"bbh XS for H2" ,"ggh XS for H3" ,"bbh XS for H3"};
    vector<string> types ={"FH_H1" ,"FH_H2" ,"FH_H3" ,"FH_Hp" ,"SH_H1" ,"SH_H2" ,"SH_H3"};
    vector<string> paths = {"FH/FH_" ,"SH_H1/SH_H1_" ,"SH_H2/SH_H2_" ,"SH_H3/SH_H3_"};
    vector<string> flags[types.size()];
    vector<string> Flags[types.size()];
    string path;
    int counter = 0;
    for(int i = 0 ; i < types.size() ; i++)
    {
        if(i < 4)
        {
            flags[i] = getFlags(types[i]);
            Flags[i] = getFlags(types[i]);
        }
        else
        {
            flags[i].push_back(SH_flags[(i-4)*2]);
            flags[i].push_back(SH_flags[(i-4)*2+1]);
            Flags[i].push_back(SH_labels[(i-4)*2]);
            Flags[i].push_back(SH_labels[(i-4)*2+1]);
        }
    }
    int total = 0;
    for(int i = 0 ; i < types.size() ; i++)
    {
        total += flags[i].size();
    }
    TH2F* h2[total];
    TFile file("tan(beta)-10_2D_CPV_13.root","RECREATE");
    for(int i = 0 ; i < types.size() ; i++)
    {
        for(int j = 0 ; j < flags[i].size() ; j++)
        {
            vector<float> tb;
            vector<float> mhp;
            for(int k = 0 ; k < N ; k++)
            {
                if(i < 4)
                    path = nameGen(paths[0] , k + 1 , ".fh-001");
                else
                    path = nameGen(paths[i-3] , k + 1 , ".out");
                if(isThere(path , flags[i][j] , types[i]) == true)
                {
                    //cout<<i<<","<<j<<","<<k<<endl;
                    if(i < 4)
                    {
                        //cout<<findTB(path , "TB")<<endl;
                        tb.push_back(strToFloat(findTB(path , "TB")));
                    }
                    else
                        tb.push_back(strToFloat(findTB(path , "tan(beta)")));
                    mhp.push_back(strToFloat(findTB(path , "MHp")));
                }
            }
            if(tb.size() > 0)
            {
                int tb_min = 0;
                int mhp_min = (int)(*min_element(mhp.begin() , mhp.end())) - 100;
                int tb_max = (int)(*max_element(tb.begin() , tb.end())) + 2;
                int mhp_max = (int)(*max_element(mhp.begin() , mhp.end())) + 100;
                h2[counter] = new TH2F((rightFlag(Flags[i][j])).c_str(),";M_{H^{+} };tan_{#beta}",(mhp_max - mhp_min + 1) * 5 + 1,mhp_min,mhp_max,(tb_max - tb_min + 1) * 20 + 1,tb_min,tb_max);
                h2[counter]->SetTitle((rightFlag(Flags[i][j])).c_str());
                for(int i = 0 ; i < tb.size() ; i++)
                    h2[counter]->Fill(mhp[i],tb[i]);
                h2[counter]->SetMarkerStyle(kFullDotLarge);
                h2[counter]->Write((rightFlag(Flags[i][j])).c_str());
                counter++;
            }
        }
    }
    //const int n_points=10;
    //double x_vals[n_points]={1,2,3,4,5,6,7,8,9,10};
    //double y_vals[n_points]={6,12,14,20,22,24,35,45,44,53};
    //double y_errs[n_points]={5,5,4.7,4.5,4.2,5.1,2.9,4.1,4.8,5.43};
    //TH2* h2 = new TH2F("X_Axis","Y_Axis",23,0,11,60,0,59);
    //for(int i = 0 ; i < n_points ; i++)
        //h2->Fill(x_vals[i],y_vals[i]);
    //TGraph graph(n_points,x_vals,y_vals);
    //h2->SetTitle("Measurement XYZ;lenght in cm;Arb Units");
    //h2->SetMarkerStyle(kFullDotLarge);
    //h2->Draw();
    file.Close();
}
string nameGen(string path ,int index ,string type)
{
    string result;
    result += path;
    result += to_string(index);
    result += type;
    return result;
}
vector<string> getFlags(string fName)
{
    vector<string> flags;
    fName += "_flags.txt";
    fstream file;
    file.open(fName,ios::in);
    string line;
    while(getline (file, line))
        flags.push_back(line);
    return flags;
}
bool findSUSY(string path , string type)
{
    fstream file;
    file.open(path,ios::in);
    string line , result;
    float bank = 0;
    string check;
    if(type.compare("FH_H1") == 0)
        check = "h0 ->";
    else if(type.compare("FH_H2") == 0)
        check = "HH ->";
    else if(type.compare("FH_H3") == 0)
        check = "A0 ->";
    else if(type.compare("FH_Hp") == 0)
        check = "Hp ->";
    else if(type.compare("FH_SM") == 0)
        check = "hSM ->";
    while(getline (file, line))
    {
        
        if(line.find("Chargino") != string::npos || line.find("chargino") != string::npos || line.find("neutralino") != string::npos || line.find("Neutralino") != string::npos || line.find("Selectron") != string::npos || line.find("Smuon") != string::npos || line.find("S_nu") != string::npos)
            if(line.find(check) != string::npos)
                return true;
    }
    return false;
}
bool isThere(string path ,string flag ,string Type)
{
    if(flag.find("-> SUSY") != string::npos)
        return findSUSY(path , Type);
    string line;
    fstream file;
    file.open(path,ios::in);
    while(getline (file, line))
    {
        if(line.find(flag) != string::npos)
            return true;
    }
    return false;
}
string findTB(string path ,string flag)
{
    string line , result = "";
    fstream file;
    file.open(path,ios::in);
    while(getline (file, line))
    {
        if(line.find(flag) != string::npos)
        {
            for(int i = 0 ; i < line.size() ; i++)
            {
                if(line[i] == '#')
                {
                    for(int j = i - 4 ; line[j] != ' ' ; j--)
                        result = line[j] + result;
                    break;
                }
            }
            break;
        }
    }
    return result;
}
string findMHp(string path ,string flag)
{
    string line , result;
    fstream file;
    file.open(path,ios::in);
    while(getline (file, line))
    {
        if(line.find(flag) != string::npos)
        {
            for(int i = 0 ; i < line.size() ; i++)
            {
                if(line[i] == '#')
                {
                    for(int j = i - 4 ; line[j] != ' ' ; j--)
                        result = line[j] + result;
                    break;
                }
            }
            break;
        }
    }
    return result;
}
float strToFloat(string base , int dp)
{
    char c[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    float result = 0 , p = 0;
    int dec = 1 , i = 0 , j , mul = 1 , mulp = 1;
    bool flag = false;
    if(base[0] == '-')
    {
        i = 1;
        mul = -1;
    }
    for(i ; base[i] != 'E' ; i++)
    {
        if(base[i] == '.')
            flag = true;
        else
        {
            int temp;
            for(int j = 0 ; j < 10 ; j++)
            {
                if(base[i] == c[j])
                    temp = j;
            }
            if(flag == false)
                result = result * 10 + temp;
            else
            {
                result = result + pow(10 , -1 * dec) * temp;
                dec ++;
            }
        }
    }
    if(base[i + 1] == '-')
    {
        mulp = -1;
    }
    j = i + 2;
    for(j ; j < base.length() ; j++)
    {
        int temp;
        for(int k = 0 ; k < 10 ; k++)
        {
            if(base[j] == c[k])
                temp = k;
        }
        p = p * 10 + temp;
    }
    p = p * mulp;
    p += dp;
    result = result * mul;
    return result * pow(10 , p);
}
string rightFlag(string flag)
{
    string result = "";
    int counter = 0;
    while(counter < flag.length())
    {
        if(flag[counter] == 'h' && flag[counter+1] == '0')
        {
            result += "H1";
            counter ++;
        }
        else if(flag[counter] == 'H' && flag[counter+1] == 'H')
        {
            result += "H2";
            counter ++;
        }
        else if(flag[counter] == 'A' && flag[counter+1] == '0')
        {
            result += "H3";
            counter ++;
        }
        else
            result += flag[counter];
        counter ++;
    }
    return result;
}
int findNumberOfFiles(string path)
{
    int result = 0;
    DIR *d;
    struct dirent *dir;
    d = opendir(path.c_str());
    if (d)
    {
        while ((dir = readdir(d)) != NULL)
        {
            if(strcmp(dir -> d_name , ".") != 0  && strcmp(dir -> d_name , "..") != 0)
                result++;
        }
    }
    return result;
}















